﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;


/**
 * 需求
 * 将其中的大部分功能都移出去，放到一个Helper中，使其与界面无关，用对象组合的方式来实现
 * 
 * 要点
 * 1. 通过对RecordCount赋值，>0激活控件，=0禁用控件。每次赋不同的值，都是外部试图要重新绑定数据的信号，如果赋新值后CurrentPageIndex
 *    处于范围之内，则不改变页号，否则重置到第0页；赋相同的值则不做处理。
 * 2. PageSize改变后，需要将所有的元素做重置
 */
namespace AMS.UI.Controls
{
    /// <summary>
    /// 
    /// </summary>
    [DefaultProperty("PageSize"),
    DefaultEvent("PageIndexChanged")]
    public partial class AmsPager : UserControl
    {
        /// <summary>
        /// 
        /// </summary>
        public AmsPager()
        {
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            InitializeComponent();
        }

        #region Events
        /// <summary>
        /// 
        /// </summary>
        public event PageIndexChangingEventHandler PageIndexChanging;

        /// <summary>
        /// 
        /// </summary>
        public event EventHandler PageSizeChanged;

        /// <summary>
        /// 
        /// </summary>
        public event EventHandler PageIndexChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnPageIndexChanging(PageIndexChangingEventArgs e)
        {
            if (PageIndexChanging != null)
            {
                PageIndexChanging(this, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void OnPageSizeChanged()
        {
            if (PageSizeChanged != null)
            {
                PageSizeChanged(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void OnPageIndexChanged()
        {
            if (PageIndexChanged != null)
            {
                PageIndexChanged(this, EventArgs.Empty);
            }
        }
        #endregion

        #region Properties
        private const int DefaultPageSize = 50;
        private int pageSize = DefaultPageSize;
        /// <summary>
        /// 
        /// </summary>
        [DefaultValue(DefaultPageSize)]
        public int PageSize
        {
            get { return pageSize; }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentNullException("值不能为负数");
                }
                if (pageSize == value)
                {
                    return;
                }

                if (!cmbPerPage.Visible && cmbPerPage.Items.Contains(pageSize.ToString()))
                {
                    throw new IndexOutOfRangeException("在列表中没有找到对应的值");
                }

                pageSize = value;
                OnPageSizeChanged();
                Reset();
            }
        }

        private int currentPageIndex;
        /// <summary>
        /// 
        /// </summary>
        /// <exception cref="IndexOutOfRangeException"></exception>
        [DefaultValue(0)]
        public int CurrentPageIndex
        {
            get { return currentPageIndex; }
            set
            {
                if ((value == 0 && PageCount == 0) || value == currentPageIndex)
                {
                    // 初始状态
                    return;
                }
                if (value < 0)
                {
                    throw new IndexOutOfRangeException("给定的值不能为负数");
                }
                if (value >= PageCount - 1)
                {
                    throw new IndexOutOfRangeException("给定的值超过了总页数");
                }

                currentPageIndex = value;
                GoToPageInternal(currentPageIndex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false)]
        public int PageCount
        {
            get
            {
                if (pageSize == 0) return 0;
                if (recordCount % pageSize == 0) return recordCount / pageSize;
                return recordCount / pageSize + 1;
            }
        }


        private int recordCount;

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false)]
        public int RecordCount
        {
            get { return recordCount; }
            set
            {
                if (value != recordCount)
                {
                    recordCount = value;
                    ResetInternal();
                    if (CurrentPageIndex >= PageCount - 1)
                    {
                        // 只有当页数
                        GoToPage(0);
                    }
                    else
                    {
                        GoToPageInternal(currentPageIndex);
                    }
                }
            }
        }

        private string pagerText = "总页数{0}，总记录数{1}";
        /// <summary>
        /// 
        /// </summary>
        [DefaultValue("总页数{0}，总记录数{1}")]
        public string PagerText
        {
            get { return pagerText; }
            set
            {
                pagerText = value;
                txtCurrentPageIndex.Text = string.Format(pagerText, PageCount, RecordCount);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [DefaultValue(true)]
        public bool CanSelectPageSize
        {
            get { return cmbPerPage.Visible; }
            set
            {
                cmbPerPage.Visible = value;
                lblPageSizeTitle.Visible = value;
            }
        }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public void NextPage()
        {
            if (currentPageIndex < PageCount - 1)
            {
                GoToPageInternal(currentPageIndex + 1);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void PriviousPage()
        {
            if (currentPageIndex > 0)
            {
                GoToPageInternal(currentPageIndex - 1);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void FirstPage()
        {
            if (currentPageIndex != 0)
            {
                GoToPageInternal(0);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void LastPage()
        {
            if (currentPageIndex < PageCount - 1)
            {
                GoToPageInternal(PageCount - 1);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageIndex"></param>
        public void GoToPage(int pageIndex)
        {
            if (pageIndex >= 0 && pageIndex < PageCount - 1)
            {
                GoToPageInternal(pageIndex);
            }
            else
            {
                throw new ArgumentOutOfRangeException("给定的值超出了现有的范围");
            }
        }

        /// <summary>
        /// 调用这个方法时，pageIndex是一个经过检验合法的值
        /// </summary>
        /// <param name="pageIndex"></param>
        private void GoToPageInternal(int pageIndex)
        {
            PageIndexChangingEventArgs args = new PageIndexChangingEventArgs(currentPageIndex, pageIndex);
            OnPageIndexChanging(args);
            if (args.Cancel)
            {
                return;
            }

            currentPageIndex = pageIndex;
            btnFirst.Enabled = (pageIndex != 0);
            btnPriv.Enabled = btnFirst.Enabled;
            btnLast.Enabled = (pageIndex < PageCount - 1);
            btnNext.Enabled = btnLast.Enabled;
            txtCurrentPageIndex.Text = pageIndex.ToString();

            OnPageIndexChanged();
        }

        /// <summary>
        /// 
        /// </summary>
        public void Reset()
        {
            ResetInternal();
            GoToPage(0);
        }

        private void ResetInternal()
        {
            btnFirst.Enabled = false;
            btnLast.Enabled = false;
            btnNext.Enabled = false;
            btnPriv.Enabled = false;

            txtCurrentPageIndex.Text = "0";
            lblTotal.Text = string.Format(pagerText, PageCount, RecordCount);
        }

        private void btn_Click(object sender, EventArgs e)
        {
            string tag = ((Control)sender).Tag.ToString();
            switch (tag)
            {
                case "next": GoToPageInternal(currentPageIndex + 1); break;
                case "privious": GoToPageInternal(currentPageIndex - 1); break;
                case "first": GoToPageInternal(0); break;
                case "last": LastPage(); break;
                default: break;
            }
        }

        private void cmbPerPage_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbPerPage.SelectedIndex >= 0)
            {
                int value;
                if (int.TryParse(cmbPerPage.SelectedItem.ToString(), out value))
                {
                    PageSize = value;
                }
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class PageIndexChangingEventArgs : EventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        public PageIndexChangingEventArgs()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="currentPageIndex"></param>
        /// <param name="newPageIndex"></param>
        public PageIndexChangingEventArgs(int currentPageIndex, int newPageIndex)
        {
            CurrentPageIndex = currentPageIndex;
            NewPageIndex = newPageIndex;
        }

        /// <summary>
        /// 
        /// </summary>
        public int CurrentPageIndex { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public int NewPageIndex { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public bool Cancel { get; set; }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void PageIndexChangingEventHandler(object sender, PageIndexChangingEventArgs e);
}
